package com.gitee.wsl.scheduler.job.runtime.scheduler

import com.gitee.wsl.scheduler.job.bean.JobStatus
import com.gitee.wsl.scheduler.job.repository.JobRepository
import com.gitee.wsl.scheduler.job.repository.LockRepository
import com.gitee.wsl.concurrent.service.ScheduledExecutorService
import com.gitee.wsl.logger.Logger
import com.gitee.wsl.logger.debug
import com.gitee.wsl.logger.error
import com.gitee.wsl.logger.getLogger
import com.gitee.wsl.scheduler.job.repository.sample.Memory
import kotlin.uuid.ExperimentalUuidApi


internal class JobCleanupScheduler(
    executorService: ScheduledExecutorService,
    period: Long,
    private val limit: Int,
    private val jobRepository: JobRepository = JobRepository.Memory,
    private val lockRepository: LockRepository = LockRepository.Memory,
) : SimplePeriodScheduler(executorService, period) {
    private val logger = Logger.getLogger<JobCleanupScheduler>()

    @OptIn(ExperimentalUuidApi::class)
    private suspend fun findAndCleanup() {
        jobRepository.findNext(emptySet(), setOf(JobStatus.SCHEDULED, JobStatus.RUNNING, JobStatus.ERROR), limit).collect { job ->
            val isAlive = job.kjobId?.let { lockRepository.exists(it) } ?: false
            if (!isAlive) {
                val applied = jobRepository.reset(job.id, job.kjobId)
                if (!applied)
                    logger.error("Couldn't reset kjob[${job.id}] with kjob id '${job.kjobId}'")
            }
        }
    }

    fun start(): Unit = run {
        logger.debug("Cleanup scheduled.")
        findAndCleanup()
    }
}